const fs = require('fs')
const path = require('path')
const util = require('util')
const loadtest = require('loadtest')
const { formatResult } = require('./libs/format')

const readdir = util.promisify(fs.readdir)

const subCommands = process.argv.slice(2)

const pathMap = {}

if (!subCommands.length) {
  console.log('You have to specify a target name')
  process.exit(-1)
}

const targetName = subCommands[0]

run()

async function run() {
  const targets = await readdir(path.resolve(__dirname, 'env'))

  if (!targets.includes(targetName)) {
    throw new Error('You are specifying a invalid target name')
  }

  const targetConfig = require(path.resolve(__dirname, 'env', targetName))

  const options = {
    url: targetConfig.host,
    method: 'GET',
    maxRequests: targetConfig.sendCount,
    concurrency: targetConfig.clientCount,
    requestsPerSecond: targetConfig.sendPerSec,
    requestGenerator(params, options, client, callback) {
      const opts = Object.assign({}, options, { path: getPath(targetConfig) })
      if (!pathMap[opts.path]) {
        pathMap[opts.path] = 0
      }
      pathMap[opts.path]++
      const request = client(opts, callback)
      return request
    },
    statusCallback(error, result, latency) {
      if (error) {
        console.log('Current latency %j, result %j, error %j', latency, result, error)
      }
    }
  }

  loadtest.loadTest(options, (error, results) => {
    if (error) {
      return console.error('Got an error: %s', error)
    }
    console.log(formatResult(results, pathMap, targetConfig))
  })
}

function getPath(targetConfig) {
  const path = getRandomElement(targetConfig.paths)
  if (!path.path) {
    throw new Error('You missed path property in your env configuration')
  }
  if (!path.params) {
    return path.path
  }
  const params = getRandomElement(path.params.slice()).slice()

  const realPath = path.path.replace(/(:[a-zA-Z_\-0-9]+)/g, () => {
    if (!params.length) {
      throw new Error(`You have invalid params for specific path ${path.path}`)
    }
    return params.shift()
  })
  return realPath
}

function getRandomElement(elms) {
  return elms[Math.floor(Math.random() * elms.length)]
}
